package com.cq.hd.member.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cq.hd.common.enums.biz.BillTypeEnum;
import com.cq.hd.common.enums.biz.BusinessRechargeApplyStateEnum;
import com.cq.hd.common.enums.biz.PayStateEnum;
import com.cq.hd.common.enums.biz.SubsidyTradeTypeEnum;
import com.cq.hd.common.pagination.Page;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.BeanUtils;
import com.cq.hd.common.utils.NoUtils;
import com.cq.hd.common.utils.StringUtils;
import com.cq.hd.member.api.dto.*;
import com.cq.hd.member.api.vo.BusinessRechargeApplyPageVo;
import com.cq.hd.member.mapper.TbBusinessMapper;
import com.cq.hd.member.mapper.TbBusinessRechargeApplyMapper;
import com.cq.hd.member.mapper.TbSubsidyAmtBillMapper;
import com.cq.hd.member.po.TbBusinessPo;
import com.cq.hd.member.po.TbBusinessRechargeApplyPo;
import com.cq.hd.member.po.TbSubsidyAmtBillPo;
import com.cq.hd.member.service.TbBusinessRechargeApplyService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 商家充值申请 服务实现类
 * </p>
 */
@Slf4j
@Service
public class TbBusinessRechargeApplyServiceImpl extends ServiceImpl<TbBusinessRechargeApplyMapper, TbBusinessRechargeApplyPo> implements TbBusinessRechargeApplyService {
    @Autowired
    private TbBusinessMapper businessMapper;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private TbSubsidyAmtBillMapper subsidyAmtBillMapper;

    @Override
    public Page<BusinessRechargeApplyPageVo> page(BusinessRechargeApplyPageDto businessRechargeApplyPageDto) {
        PageHelper.startPage(businessRechargeApplyPageDto.getPageNum(), businessRechargeApplyPageDto.getPageSize());
        List<BusinessRechargeApplyPageVo> businessRechargeApplyPageVos = baseMapper.listByDto(businessRechargeApplyPageDto);
        PageInfo<BusinessRechargeApplyPageVo> pageInfo = new PageInfo<>(businessRechargeApplyPageVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public int apply(BusinessRechargeApplyDto businessRechargeApplyDto) {
        TbBusinessPo tbBusinessPo = businessMapper.selectById(businessRechargeApplyDto.getBusinessId());
        if (tbBusinessPo == null || tbBusinessPo.getDelState() != 0) {
            Throw.isBusinessException("未找到商家数据");
        }

        String paymentNo = businessRechargeApplyDto.getPaymentNo();
        BigDecimal tradeAmt = businessRechargeApplyDto.getTradeAmt();
        String paymentImage = businessRechargeApplyDto.getPaymentImage();
        if (paymentNo == null || paymentNo.isEmpty()) {
            Throw.isBusinessException("请输入打款单号");
        }
        // 打款单号唯一校验
        Long businessRechargeApplyId = baseMapper.getIdByPaymentNo(paymentNo);
        if (businessRechargeApplyId != null) {
            Throw.isBusinessException("打款单号已经存在");
        }

        if (tradeAmt == null || tradeAmt.compareTo(BigDecimal.valueOf(0)) <= 0) {
            Throw.isBusinessException("请输入打款金额");
        }
        if (paymentImage == null || paymentImage.isEmpty()) {
            Throw.isBusinessException("请上传打款凭证");
        }

        TbBusinessRechargeApplyPo businessRechargeApplyPo = new TbBusinessRechargeApplyPo();
        BeanUtils.copyProperties(businessRechargeApplyDto, businessRechargeApplyPo);
        businessRechargeApplyPo.setApplyNo(NoUtils.getBusinessRechargeApplyNo());
        businessRechargeApplyPo.setCreateTime(LocalDateTime.now());
        businessRechargeApplyPo.setUpdateTime(LocalDateTime.now());
        return baseMapper.insert(businessRechargeApplyPo);
    }

    @Override
    public Boolean audit(BusinessRechargeApplyAuditDto businessRechargeApplyAuditDto) {
        TbBusinessRechargeApplyPo businessRechargeApplyPageVo = getValidPo(businessRechargeApplyAuditDto);

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            // 记录审核时间，修改充值申请单状态
            businessRechargeApplyAuditDto.setAuditTime(LocalDateTime.now());
            int res = baseMapper.updateByAuditDto(businessRechargeApplyAuditDto);
            if (res == 0) {
                Throw.isBusinessException("更新商家补贴充值申请状态失败");
            }

            // 如果是审核通过，增加商家补贴金额，并写入补贴资金变动记录
            if (businessRechargeApplyAuditDto.getState().equals(BusinessRechargeApplyStateEnum.AUDIT_SUCCESS.getValue())) {
                // 记录补贴金额变动记录
                res = addSubsidyAmtBill(businessRechargeApplyPageVo);
                if (res == 0) {
                    log.error("增加商家补贴金充值流水失败: businessRechargeApplyId：{}", businessRechargeApplyPageVo.getId());
                    Throw.isBusinessException("增加商家补贴金充值流水失败");
                }

                // 增加商家补贴金额
                res = businessMapper.addSubsidyAmt(businessRechargeApplyPageVo.getBusinessId(), businessRechargeApplyPageVo.getTradeAmt());
                if (res == 0) {
                    Throw.isBusinessException("审核通过，增加商家补贴金额失败");
                }
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<商家补贴充值申请审核>事务异常回滚", e);
            return false;
        }

        return true;
    }

    private TbBusinessRechargeApplyPo getValidPo(BusinessRechargeApplyAuditDto businessRechargeApplyAuditDto) {
        if (businessRechargeApplyAuditDto.getState().equals(BusinessRechargeApplyStateEnum.AUDIT_FAIL.getValue())) {
            if (StringUtils.isBlank(businessRechargeApplyAuditDto.getRefuseReason())) {
                Throw.isBusinessException("请填写审核不通过原因");
            }
        } else if (!businessRechargeApplyAuditDto.getState().equals(BusinessRechargeApplyStateEnum.AUDIT_SUCCESS.getValue())) {
            Throw.isBusinessException("审核状态有误");
        }

        TbBusinessRechargeApplyPo businessRechargeApplyPageVo = baseMapper.selectById(businessRechargeApplyAuditDto.getId());
        if (businessRechargeApplyPageVo == null) {
            Throw.isBusinessException("充值申请不存在");
        }
        if (!businessRechargeApplyPageVo.getState().equals(BusinessRechargeApplyStateEnum.WAIT_AUDIT.getValue())) {
            Throw.isBusinessException("该充值申请已经审核过");
        }

        return businessRechargeApplyPageVo;
    }

    private int addSubsidyAmtBill(TbBusinessRechargeApplyPo businessRechargeApplyPo) {
        Long businessId = businessRechargeApplyPo.getBusinessId();
        TbBusinessPo businessPo = businessMapper.selectById(businessId);
        if (businessPo == null) {
            Throw.isBusinessException("商家不存在");
        }
        BigDecimal subsidyAmt = businessPo.getSubsidyAmt();
        BigDecimal tradeAmt = businessRechargeApplyPo.getTradeAmt();

        // 加商家补贴金流水
        TbSubsidyAmtBillPo tbSubsidyAmtBillPo = new TbSubsidyAmtBillPo();
        tbSubsidyAmtBillPo.setBusinessId(businessId);
        tbSubsidyAmtBillPo.setUserId(businessPo.getUserId());
        tbSubsidyAmtBillPo.setOrderNo(NoUtils.getSubsidyOrderNo());
        tbSubsidyAmtBillPo.setBillType(BillTypeEnum.INCOME.getValue());
        tbSubsidyAmtBillPo.setTradeType(SubsidyTradeTypeEnum.RECHARGE.getValue());
        tbSubsidyAmtBillPo.setRelationTradeNo(businessRechargeApplyPo.getApplyNo());
        tbSubsidyAmtBillPo.setBeforeAmt(subsidyAmt);
        tbSubsidyAmtBillPo.setTradeAmt(tradeAmt);
        tbSubsidyAmtBillPo.setAfterAmt(subsidyAmt.add(tradeAmt));
        tbSubsidyAmtBillPo.setPayState(PayStateEnum.SUCCESS.getValue());
        tbSubsidyAmtBillPo.setRemark("商家补贴充值申请");
        tbSubsidyAmtBillPo.setTradeTime(LocalDateTime.now());
        tbSubsidyAmtBillPo.setCreateTime(LocalDateTime.now());
        tbSubsidyAmtBillPo.setUpdateTime(LocalDateTime.now());
        return subsidyAmtBillMapper.insert(tbSubsidyAmtBillPo);
    }
}
